<?php
namespace Duobao\Controller;

use Duobao\Controller\LogController as MyLog;
use Duobao\Model\WeixinModel as Weixin;
use Com\Weixin\WeixinJs as WeixinJs;
use Com\Weixin\WXBizMsgCrypt as WxCrypt;
use Com\Weixin\WeixinApi as WeixinApi;
use Duobao\Model\DBConfModel as DBConf;

class WeixinController extends ControllerBase{
    private $textTpl = "<xml>
							<ToUserName><![CDATA[%s]]></ToUserName>
							<FromUserName><![CDATA[%s]]></FromUserName>
							<CreateTime>%s</CreateTime>
							<MsgType><![CDATA[%s]]></MsgType>
							<Content><![CDATA[%s]]></Content>
							</xml>";
    /**
     * 默认
     */
    public function index()
    {
        echo "<!--hi , i'm from " . MODULE_NAME . "~" . APP_STATUS, "-->";
    }

    /**
     * 返回签名包
     */
    public function getSignPackage(){
        $ret = array();
        $ret['status'] = 200;
        $ret['msg'] = '';
        $ret['data'] = array();

        try{
            $url = I('post.url');
            if(!empty($url)){
                $model = new WeixinJs(C('AppID'),C('AppSecret'));
                $signature = $model->getSignPackage(urldecode($url));
                if($signature){
                    $ret['data']['signature']=$signature;
                }else{
                    $ret['status'] = 500;
                    $ret['msg'] = empty('签名失败');
                }
            }else{
                $ret['status'] = 403;
                $ret['msg'] = empty('empty of url');
            }
        }catch (\Exception $e){
            $ret['status'] = $e->getCode();
            $ret['msg'] = $e->getMessage();
        }

        return $this->response($ret);
    }

    /**
     * 微信绑定验证服务器
     */
    public function wxSerivce(){
        if(isset($_GET['echostr'])){
            #MyLog::write('签名');
            $this->checkSignature();
        }else{
            #MyLog::write('响应消息');
            $this->responseMsg();
        }
    }

    /**
     * 验证微信服务器vlide
     */
    public function checkSignature(){
        $signature = $_GET["signature"];
        $timestamp = $_GET["timestamp"];
        $nonce = $_GET["nonce"];

        $token = C('token');
        $tmpArr = array($token, $timestamp, $nonce);
        sort($tmpArr);
        $tmpStr = implode( $tmpArr );
        $tmpStr = sha1( $tmpStr );

        if($tmpStr == $signature){
            #MyLog::write('token验证成功');
            echo $_GET['echostr'];
            exit;
        }
    }

    /**
     * 返回用户的信息
     */
    private function responseMsg(){
       # MyLog::write('进入消息响应');
        //get post data, May be due to the different environments
        $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];

        //extract post data
        if (!empty($postStr)){

            #解密消息
            $postObj = simplexml_load_string( $this->decryptMsg($postStr), 'SimpleXMLElement', LIBXML_NOCDATA);

            $RX_TYPE = trim($postObj->MsgType);
            #ob_start();
            #var_dump($postObj);
            #MyLog::write(ob_get_contents());
            switch($RX_TYPE)
            {
                case "text":
                   # MyLog::write('进入文本消息');
                    $resultStr = $this->handleText($postObj);
                    break;
                case "event":
                    $resultStr = $this->handleEvent($postObj);
                    break;
                default:
                    #$resultStr = "Unknow msg type: ".$RX_TYPE;
                    $resultStr = '';
                    break;
            }
//            ob_start();
//            var_dump($resultStr);
//
//            $this->log('str:'.ob_get_contents());
            if($resultStr){
                echo $this->encryptMsg($resultStr);
            }else{
                echo '';
                exit;
            }
        }else {
            echo "";
            exit;
        }
    }

    /**
     * 处理微信的文本消息
     */
    private function handleText($postObj){
        $dbconf = new DBConf();
        $wx_welcome_text = $dbconf->getConfField('wx_welcome_text');
        $wx_welcome_url = C('wx_welcome_url');

        #MyLog::write('处理文本消息');
       $fromUser = $postObj->FromUserName;
       $toUser = $postObj-> ToUserName;
       $keyword = trim($postObj->Content);
       $time = time();
       $msgType = 'text';
       if($keyword =='time'){
           #MyLog::write('进入time');

           $contentStr  = time();
           return  sprintf($this->textTpl, $fromUser, $toUser, $time, $msgType, $contentStr);

       }else{
           $keyword = '您的留言我已经收到；我们会在24小时内回复您！感谢您的留言。如果您有任何疑问请联系微信客服'.C('Customer_service')."\n <a href='".$wx_welcome_url."'>".$wx_welcome_text."</a>";
           return  sprintf($this->textTpl, $fromUser, $toUser, $time, $msgType, $keyword);

       }

    }

    /**
     * 处理微信事件消息
     */
    private function handleEvent($postObj){
        $contentStr = "";
        switch ($postObj->Event)
        {
            case "subscribe":
                $contentStr = $this->randText();
                #postObj中包含了用户的openid，通过openid获取用户的信息掺入数据库
                $result = $this->insertUser2($postObj->FromUserName);#插入用户结果
                if(!$result){
                    MyLog::write('用户添加失败Controller：WeixinController,line:176');
                }
                #MyLog::write($contentStr);
                break;
            case 'unsubscribe':
                $contentStr='';
                break;
            default :
                $contentStr = "Unknow Event: ".$postObj->Event;
                break;
        }

        return  sprintf($this->textTpl, $postObj->FromUserName, $postObj->ToUserName, time(), 'text', $contentStr);
    }

    /**
     * 用户进入公众号，通过openid获取用户信息，插入到数据
     */
    public function insertUser2($openId){
        #MyLog::write('进入插入用户');
        #1、获取access_token
        $weixinApi = new WeixinApi();
        $access_token = $weixinApi->getToken();
        #$this->log($access_token);
        $request_url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=$access_token&openid=$openId&lang=zh_CN";
        $result = https_request($request_url);

        $result = json_decode($result);

//        ob_start();
//        var_dump($result);
//        MyLog::write(ob_get_contents());
        #装换为数组
        $result = objToArr($result);

        #判断在获取用户信息的时候是否存在错误，如果存在错误在数据库中记录日志
        if(array_key_exists('errcode',$result)){
            ob_start();
            var_dump($result);
            MyLog::write(ob_get_contents());
            MyLog::write($result.'/weixin返回errorcode');
            return false;
        }else{
            #微信返回没有错误，数据库操作
            #MyLog::write('没有错误');
            $model = new Weixin();
            return  $model->existUser2($result);
        }

    }

    /**
     * 用户进入公众号，通过openid获取用户信息，插入到数据
     */
    public function insertUser($openId){
        #MyLog::write('进入插入用户');
        #1、获取access_token
        $weixinApi = new WeixinApi();
        $access_token = $weixinApi->getToken();
        #$this->log($access_token);
        $request_url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=$access_token&openid=$openId&lang=zh_CN";
        $result = https_request($request_url);

        $result = json_decode($result);

//        ob_start();
//        var_dump($result);
//        MyLog::write(ob_get_contents());
        #装换为数组
       $result = objToArr($result);

        #判断在获取用户信息的时候是否存在错误，如果存在错误在数据库中记录日志
        if(array_key_exists('errcode',$result)){
            ob_start();
            var_dump($result);
            MyLog::write(ob_get_contents());
            MyLog::write($result.'/weixin返回errorcode');
            return false;
        }else{
            #微信返回没有错误，数据库操作
            #MyLog::write('没有错误');
            $model = new Weixin();
            return  $model->existUser($result);
        }
    }

    /**
     * 关注事件随机函数
     */
    private function randText(){
        $dbconf = new DBConf();
        $wx_welcome_text = $dbconf->getConfField('wx_welcome_text');
        $wx_welcome_url = C('wx_welcome_url');

        $text = array(
            "呀！一不小心我们就成为了微信好友啦，我在这里恭候大驾多时，从现在开始您可以随时随地进行".C('APP_NAME')."的微信用户专享服务！请直接点击底部菜单，找寻属于你的专属宝物，畅享夺宝过程中的乐趣！ ",
            "大家都已经加入".C('APP_NAME')."，这块地方已不是秘密，但是我们的宝物只会越来越多，越来越有趣，不然就点击下面的菜单，开启你的夺宝之旅吧 ",
            '激动人心的时刻即将到来，让我们试目以待谁是最后的幸运者！ ',
        );

        $index = rand(0,2);
        #MyLog::write($index);
        return $text[$index]."\n<a href='".$wx_welcome_url."'>".$wx_welcome_text."</a>";
    }

    /**
     * 解密消息
     */
    private function decryptMsg($postStr){
        $wxCrypt = new WxCrypt(C('token'),C('EncodingAESKey'),C('AppID'));
        $timestamp = $_GET['timestamp'];
        $nonce = $_GET["nonce"];
        $msg_signature = $_GET['msg_signature'];

        $decryptMsg = '';
        $errcode = $wxCrypt->decryptMsg($msg_signature,$timestamp,$nonce,$postStr,$decryptMsg);

        if($errcode != 0){
            $this->log("file:".__FILE__."--error--:decrypt error");
        }

        return $decryptMsg;
    }

    /**
     * 加密消息
     */
    private function encryptMsg($content){
        #$this->log('进入加密');
        $wxCrypt = new WxCrypt(C('token'),C('EncodingAESKey'),C('AppID'));
        $encryptMsg = '';#存储加密后的串
        $errcode = $wxCrypt->encryptMsg($content,time(),$this->createNonceStr(),$encryptMsg);

        if($errcode != 0){
            $this->log('encryptMsg fail:' . $errcode);
        }
        #$this->log('加密完成');

        return $encryptMsg;
    }

    /**
     * 产生16为加密串
     */
    private function createNonceStr($length = 16)
    {
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i ++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    /**
     * 记录日志
     */
    private function log($content){
        MyLog::write($content);
    }
    /*end weixin controller*/
}